use std::{future::Future, ops::{Deref, DerefMut}, pin::Pin};
use actix_web::{dev::Payload, FromRequest, HttpRequest};
use bytes::{BufMut, BytesMut};
use futures::StreamExt;
use serde::{de::DeserializeOwned, Deserialize};
use crate::error::{AppErr, ErrorWrap};

const MAX_CBOR_SIZE: usize = 30 * 1024 * 1024; // 30MB


#[derive(Debug, Deserialize)]
pub struct Cbor<T>(pub T);

impl<T> Deref for Cbor<T> {

    type Target = T;

    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

impl <T> DerefMut for Cbor<T> {

    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.0
    }
}

async fn parse_cbor<T: DeserializeOwned>(mut payload: Payload) -> Result<Cbor<T>, AppErr> {
    
    let mut bytes = BytesMut::new();
    while let Some(part) = payload.next().await {
        let buf = part.wrap()?;
        if (bytes.len() + buf.len()) > MAX_CBOR_SIZE {
            return Err(AppErr::Static("发送数据过大"));
        }
        bytes.put_slice(&buf);
    }
    let value: T = serde_cbor::from_slice(&bytes)?;
    Ok( Cbor(value) )
}

impl<T: DeserializeOwned + 'static> FromRequest for Cbor<T> {

    type Error = AppErr;
    type Future = Pin<Box<dyn Future<Output = Result<Self, AppErr>>>>;
    
    fn from_request(_req: &HttpRequest, payload: &mut Payload) -> Self::Future {
        let payload = payload.take();
        Box::pin( parse_cbor(payload) )
    }
}















